
#include "CEngine.h"
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>

inline WAMRef getAux(struct WAMData *s, int i){
  return s->auxRegisters[i];
}

inline void setAux(struct WAMData *s,int i,WAMRef v){
  s->auxRegisters[i] = v;
}

struct WAMData *newWAMData_c(){
  /* no malloc checks ... */
  return (struct WAMData *)malloc(sizeof(struct WAMData));
}

void zeroICCount (struct ICCount *i){
  i->deductiveCount=0;
  i->inductiveCount=0;
  i->globalCount=0;
}

struct ICCount *newICCount_c(){
  /* no malloc checks ... */
  struct ICCount *ret = (struct ICCount *)malloc(sizeof(struct ICCount));
  printf("ALLOC - PTR is %p\n",ret);
  zeroICCount(ret);
  return ret;
}

void incICCount (struct ICCount *i) {
  i->deductiveCount++;
  i->inductiveCount++;
  i->globalCount++;
  /* printf("ICCount AFTER; ded %"PRIu64", ind %"PRIu64", glob %"PRIu64"\n",i->deductiveCount,i->inductiveCount,i->globalCount); */
}

void zeroICDeductiveCount(struct ICCount *i){ i->deductiveCount = 0; }

void zeroICInductiveCount(struct ICCount *i){ i->inductiveCount = 0; }

uint64_t getDeductiveCount(struct ICCount *i) {  return i->deductiveCount; }
uint64_t getInductiveCount(struct ICCount *i) {  return i->inductiveCount; }
uint64_t getGlobalCount(struct ICCount *i) {  return i->globalCount; }



/* next is from EngineTypes.hs */
#define haltop 0x01 
/* XXX - I think these next "LL"s assume a uint64 is an LL */
inline int getOp(WAMOpRaw c) { return (int)((c &  (uint64_t)0xFF00000000000000LL) >> 56); }
inline int isAuxOp(WAMOpRaw c){ return (c & (uint64_t)0x8000000000000000LL) != 0;}

void haskell_exit();

void execCode (void *wd,struct ICCount *i, struct ICCount *c){

  WAMOpRaw code;
  WAMOpRaw codeaux;
  int ongoing;
  uint64_t gc;

  while(1){
    // increment counts
    incICCount(c);
    incICCount(i);
#define DEBUG_GLOBAL_BAILOUT 3000000

#ifdef DEBUG_GLOBAL_BAILOUT
    gc = i->globalCount;
    if(gc > DEBUG_GLOBAL_BAILOUT){
      printf("Quitting ... \n");
      haskell_exit();
    }
#endif

    code = getCodeEntryInst(wd);
    ongoing = getQueryResult(wd);
    if(getOp(code) != haltop && ongoing){

      // pc = getPC(wd); /* only used for display */
      if(! (isAuxOp(code))){
	execCodeEntryInst(wd,code);
      }else{
	codeaux = getCodeEntryAux(wd);
	execCodeEntryInstAux(wd,code,codeaux);
      }
      incPC(wd);
    }else{
      break;
    }
  }
}




